package com.mgee.netty.server.netty;

import java.util.Date;
import java.util.Timer;

import com.mgee.netty.server.pojo.NewChatUserInfo;
import org.apache.commons.lang3.StringUtils;

import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
import com.mgee.netty.server.constant.MessagingConst;
import com.mgee.netty.server.pojo.ChatLogInfo;
import com.mgee.netty.server.pojo.ChatUserInfo;
import com.mgee.netty.server.pojo.SessionCloseReason;
import com.mgee.netty.server.protobuf.ImProto;
import com.mgee.netty.server.util.ChannelUtils;
import com.mgee.netty.server.util.DateUtil;

import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
/**
 * 通信session
 * @author mileswan
 *
 */
@Slf4j
public class IoSession {
 
	/** 网络连接channel */
	private Channel channel;
 
	private ChatUserInfo user;
	/** ip地址 */
	private String remoteIp;

	private NewChatUserInfo newChatUserInfo;


	/**
	 * 是否主动发送过心跳
	 */
	private boolean heartbeated;
	
	private ChatLogInfo private_chat_log;
	
	private ChatLogInfo group_chat_log;
	
	private ChatLogInfo world_chat_log;
	// 会话连接时间
	private Date joinTime;
	// 客户端主动断开时间
	private Date clientDisconnectTime;
	// 定时器
	private Timer timer;
	
	private SessionCloseReason sessionCloseReason = null;
	
	public void setSessionCloseReason(SessionCloseReason sessionCloseReason) {
		this.sessionCloseReason = sessionCloseReason;
	}
	
	public Date getJoinTime() {
		return joinTime;
	}
	
	public Date getClientDisconnectTime() {
		return clientDisconnectTime;
	}
	
	public void setClientDisconnectTime(Date clientDisconnectTime) {
		this.clientDisconnectTime = clientDisconnectTime;
	}
	
	public ChatLogInfo getPrivate_chat_log() {
		return private_chat_log;
	}

	public void setPrivate_chat_log(ChatLogInfo private_chat_log) {
		this.private_chat_log = private_chat_log;
	}

	public ChatLogInfo getGroup_chat_log() {
		return group_chat_log;
	}

	public void setGroup_chat_log(ChatLogInfo group_chat_log) {
		this.group_chat_log = group_chat_log;
	}

	public ChatLogInfo getWorld_chat_log() {
		return world_chat_log;
	}

	public void setWorld_chat_log(ChatLogInfo world_chat_log) {
		this.world_chat_log = world_chat_log;
	}

	/** 拓展用，保存一些个人数据  */
//	private Map<String, Object> attrs = new HashMap<>();
 
	@SuppressWarnings("unused")
	private IoSession() {
 
	}
 
	public IoSession(Channel channel) {
		this.channel = channel;
		this.remoteIp = ChannelUtils.getRemoteIp(channel);
		this.heartbeated = false;
		joinTime = DateUtil.now();
		/*
		 * timer = new Timer(); timer.schedule(new TimerTask() {
		 * 
		 * @Override public void run() { // log.info("timer detect..."); if(null !=
		 * getUser()) { timer.cancel(); }else if(DateUtil.getSecondsValue(joinTime) >
		 * 10) { // 超过10秒还未登录则断开session close(SessionCloseReason.UNAUTHORIZED); } } },
		 * 0,1000);
		 */
	}
	
	public void setUser(ChatUserInfo user) {
		this.user = user;
	}
	public NewChatUserInfo getNewChatUserInfo() {
		return newChatUserInfo;
	}
	public void setNewChatUserInfo(NewChatUserInfo newChatUserInfo) {
		this.newChatUserInfo = newChatUserInfo;
	}
	
	public Channel getChannel() {
		return channel;
	}
	
	/**
	 * 向客户端发送消息
	 * @param msg
	 */
	public void sendMessage(ImProto.ImMsg msg) {
		if (msg == null) {
			return;
		}
		if (channel != null) {
			channel.writeAndFlush(msg);
			if(!MessagingConst.TYPE_UPOS_RESPONSE.equals(msg.getMsg().getTypeUrl()) && !MessagingConst.TYPE_UPOS_REQUEST.equals(msg.getMsg().getTypeUrl())) {
				
				try {
					String uid="";
					if(newChatUserInfo != null && StringUtils.isNotBlank(newChatUserInfo.getUid())) {
						uid = newChatUserInfo.getUid();
					}
					log.info("Outbound message1 is :" + JsonFormat.printer().usingTypeRegistry(SessionManager.typeRegistry).print(msg.toBuilder())
							+ ", to user " + uid);
				} catch (InvalidProtocolBufferException e) {
					log.info("Outbound message2 is :" + msg.toString());
				}
			}
			
		}
	}

	/**
	 * 向客户端发送消息
	 * @param msg
	 */
	public void sendMessageTwo(ImProto.ImMsg msg) {
		if (msg == null) {
			return;
		}
		if (channel != null) {
			channel.writeAndFlush(msg);
			if(!MessagingConst.TYPE_UPOS_RESPONSE.equals(msg.getMsg().getTypeUrl()) && !MessagingConst.TYPE_UPOS_REQUEST.equals(msg.getMsg().getTypeUrl())) {

				try {
					String uid="";
					if(newChatUserInfo != null && StringUtils.isNotBlank(newChatUserInfo.getUid())) {
						uid = newChatUserInfo.getUid();
					}
					log.info("NewOutbound message1 is :" + JsonFormat.printer().usingTypeRegistry(SessionManager.typeRegistry).print(msg.toBuilder())
							+ ", to user " + uid);
				} catch (InvalidProtocolBufferException e) {
					log.info("NewOutbound message2 is :" + msg.toString());
				}
			}

		}
	}
 
	public String getRemoteIp() {
		return remoteIp;
	}
 
	public void setRemoteIp(String ipAddr) {
		this.remoteIp = ipAddr;
	}
 
	public boolean isHeartbeated() {
		return heartbeated;
	}
 
	public void setHeartbeated(boolean heartbeated) {
		this.heartbeated = heartbeated;
	}
 
	public ChatUserInfo getUser() {
		return user;
	}

	public NewChatUserInfo getNewUser() {
		return newChatUserInfo;
	}
	
	public boolean isClose() {
		if (channel == null) {
			return true;
		}
		return !channel.isActive() ||
			   !channel.isOpen();
	}
	
	/**
	 * 关闭session 
	 * @param reason {@link SessionCloseReason}
	 */
	public void close() {
		try{
			if (this.timer != null) {
				timer.cancel();
			}
			if (this.channel == null) {
				return;
			}
			if (channel.isOpen()) {
				channel.close();
				log.info("close session[{}], reason is {}", getUser()==null?channel.id():getUser().getUid(), sessionCloseReason == null?SessionCloseReason.NORMAL:sessionCloseReason);
			}else{
				log.info("session[{}] already close, reason is {}", getUser()==null?channel.id():getUser().getUid(), sessionCloseReason == null?SessionCloseReason.NORMAL:sessionCloseReason);
			}
		}catch(Exception e){
			log.error("close session exception: ", e);
		}
	}
	
	public void close(SessionCloseReason sessionCloseReason) {
		this.sessionCloseReason = sessionCloseReason;
		close();
	}
 
}
